package com.hww.common;

import android.app.Application;
import android.util.Log;

import java.lang.reflect.Method;

/**
 * @author hww
 * @date 2020/10/20
 * email：
 * description： 通过反射获取应用的application对象
 */
public class MyAppThis {
    private static Application application;

    public static Application getThis() {
        if (null == application) {
            synchronized (MyAppThis.class) {
                if (null == application) {
                    new MyAppThis();
                }
            }
        }
        return application;
    }

    /**
     * 通过手动设置application对象
     *
     * @param context
     */
    public static void init(Application context) {
        application = context;
    }

    /**
     * 通过反射获取应用的 application 对象
     */
    private MyAppThis() {

        try {
            // 通过反射获取 ActivityThread 类
            Class<?> activityThreadClass = Class.forName("android.app.ActivityThread");
            // 获取 currentActivityThread 方法
            Method currentActivityThreadMethod = activityThreadClass.getDeclaredMethod("currentActivityThread");
            currentActivityThreadMethod.setAccessible(true);
            // 调用 currentActivityThread 方法获取 ActivityThread 实例
            Object activityThread = currentActivityThreadMethod.invoke(null);
            // 获取 getApplication 方法
            Method getApplicationMethod = activityThreadClass.getDeclaredMethod("getApplication");
            getApplicationMethod.setAccessible(true);
            // 调用 getApplication 方法获取当前 Application 实例
            Application applicationT = (Application) getApplicationMethod.invoke(activityThread);

            application = applicationT;
            Log.e("MyAppThis", "curApp class2:" + application);
        } catch (Exception e) {
            Log.e("MyAppThis", "e:" + e.toString());
        }

        if (application != null) {
            return;
        }

        try {
            /*通过反射获取 ActivityThread 类*/
            Class atClass = Class.forName("android.app.ActivityThread");
            /*获取 currentApplication 方法*/
            Method currentApplicationMethod = atClass.getDeclaredMethod("currentApplication");
            currentApplicationMethod.setAccessible(true);
            application = (Application) currentApplicationMethod.invoke(null);
            Log.e("MyAppThis", "curApp class2:" + application);
        } catch (Exception e) {
            Log.e("MyAppThis", "e:" + e.toString());
        }

        if (application != null) {
            return;
        }

        try {
            Class atClass = Class.forName("android.app.AppGlobals");
            Method currentApplicationMethod = atClass.getDeclaredMethod("getInitialApplication");
            currentApplicationMethod.setAccessible(true);
            application = (Application) currentApplicationMethod.invoke(null);
            Log.e("MyAppThis", "curApp class3:" + application);
        } catch (Exception e) {
            Log.e("MyAppThis", "e:" + e.toString());
        }

    }
}